// 2025/4/7: 首个版本
// 2025/6/12: 协议名常量改为public

package com.appox.samples;

import com.appox.Sample;
import com.appox.GeneralSample;
import com.appox.GeneralElement;
import com.appox.Types;
import java.util.ArrayList;
import java.util.List;

/**
 * 可行驶区域样本数据类
 */
public class FreespaceSample extends Sample {

    private List<Types.FloatPoint[]> sequences; // [m] 可行驶区域顶点列表(可多段描述)

    /**
     * 构造函数，初始化点序列列表
     */
    public FreespaceSample() {
        sequences = new ArrayList<>();
    }

    /**
     * 获取点序列列表
     */
    public List<Types.FloatPoint[]> getSequences() {
        return sequences;
    }

    /**
     * 设置点序列列表
     */
    public void setSequences(List<Types.FloatPoint[]> sequences) {
        this.sequences = sequences;
    }

    /**
     * 将可行驶区域样本转换为通用样本
     */
    public GeneralSample toGeneralSample(int channel) {
        GeneralSample result = new GeneralSample();
        result.setTime(this);
        result.setProtocol(TARGET_PROTOCOL);
        result.setChannel(channel);
        
        if (sequences == null || sequences.isEmpty()) {
            // 如果没有序列，只添加序列计数为0
            GeneralElement[] values = new GeneralElement[1];
            values[0] = new GeneralElement(0.0);
            result.setValues(values);
            result.setNumberOfSignificants(1);
            return result;
        }
        
        // 计算点的总数
        int pointCount = 0;
        for (Types.FloatPoint[] sequence : sequences) {
            pointCount += sequence.length;
        }
        
        // 创建数组，预先分配足够的空间
        // 格式：[序列数量, 序列1偏移量, 序列1点数, 序列2偏移量, 序列2点数, ..., 点1X, 点1Y, 点2X, 点2Y, ...]
        GeneralElement[] values = new GeneralElement[1 + 2 * sequences.size() + 2 * pointCount];
        
        // 初始化所有元素
        for (int i = 0; i < values.length; i++) {
            values[i] = new GeneralElement();
        }
        
        int seqBase = 1;
        int ptBase = seqBase + 2 * sequences.size();
        
        // 设置序列数量
        values[0] = new GeneralElement((double)sequences.size());
        
        // 循环处理每个序列
        pointCount = 0;
        for (int i = 0; i < sequences.size(); i++) {
            Types.FloatPoint[] pts = sequences.get(i);
            
            // 设置点偏移量和点数量
            values[seqBase + 2 * i] = new GeneralElement((double)pointCount);
            values[seqBase + 2 * i + 1] = new GeneralElement((double)pts.length);
            
            // 设置点坐标
            for (int n = 0; n < pts.length; n++) {
                values[ptBase + 2 * (pointCount + n)] = new GeneralElement((double)pts[n].getX());
                values[ptBase + 2 * (pointCount + n) + 1] = new GeneralElement((double)pts[n].getY());
            }
            
            pointCount += pts.length;
        }
        
        result.setValues(values);
        result.setNumberOfSignificants(values.length);
        
        return result;
    }
    
    /**
     * 获取通用样本协议
     */
    @Override
    public String getGeneralSampleProtocol() {
        return TARGET_PROTOCOL;
    }
    
    /**
     * 获取通用样本协议列表
     */
    @Override
    public String[] getGeneralSampleProtocols() {
        return PROTOCOLS;
    }
    
    /**
     * 从通用样本转换为可行驶区域样本
     */
    @Override
    public boolean fromGeneralSample(GeneralSample sample) {
        setTime(sample);
        
        String protocol = sample.getProtocol();
        if (TARGET_PROTOCOL.equals(protocol)) {
            return fromFreespaceSampleV1(sample);
        }
        
        return false;
    }
    
    /**
     * 从通用样本V1版本转换为可行驶区域样本
     */
    private boolean fromFreespaceSampleV1(GeneralSample sample) {
        GeneralElement[] values = sample.getValues();
        if (values == null || values.length < 1 || !values[0].isValid()) {
            return false;
        }
        
        int seqCount = (int)values[0].getValue();
        if (values.length < 1 + 2 * seqCount) {
            return false;
        }
        
        int seqBase = 1;
        int ptBase = seqBase + 2 * seqCount;
        
        List<Types.FloatPoint[]> list = new ArrayList<>();
        for (int i = 0; i < seqCount; i++) {
            if (!values[seqBase + 2 * i].isValid() || !values[seqBase + 2 * i + 1].isValid()) {
                return false;
            }
            
            int ptOffset = (int)values[seqBase + 2 * i].getValue();
            int ptCount = (int)values[seqBase + 2 * i + 1].getValue();
            
            if (values.length < ptBase + 2 * (ptOffset + ptCount)) {
                return false;
            }
            
            Types.FloatPoint[] pts = new Types.FloatPoint[ptCount];
            for (int n = 0; n < ptCount; n++) {
                if (!values[ptBase + 2 * (ptOffset + n)].isValid() || 
                    !values[ptBase + 2 * (ptOffset + n) + 1].isValid()) {
                    return false;
                }
                
                pts[n] = new Types.FloatPoint();
                pts[n].setX((float)values[ptBase + 2 * (ptOffset + n)].getValue());
                pts[n].setY((float)values[ptBase + 2 * (ptOffset + n) + 1].getValue());
            }
            
            list.add(pts);
        }
        
        sequences = list;
        return true;
    }
    
    // 协议相关常量
    public static final String TARGET_PROTOCOL = "freespace-sample-v1";
    public static final String[] PROTOCOLS = {
        "freespace-sample-v1"
    };
} 